{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. 列表解析和函数式编程工具  \n",
    "列表解析能够更加通用，可以在一个列表解析中编写任意数量的嵌套的 for 循环，并且每一个都有可选的关联的 if 测试：\n",
    "```\n",
    "[expression for target1 in iterable1 [if condition1]\n",
    "        for target2 in iterable2 [if condition2] ...\n",
    "        for targetN in iterableN [if conditionN] ]\n",
    "```\n",
    "当 for 分句嵌套在列表解析中时，就像等效的嵌套的 for 循环语句。  \n",
    "\n",
    "这种相同的语法继承自集合和字典解析式以及生成器表达式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[100, 200, 300, 101, 201, 301, 102, 202, 302]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x + y for x in [0, 1, 2] for y in [100, 200, 300]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['sP', 'sA', 'mP', 'mA']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x + y for x in 'spam' if x in 'sm' for y in 'SPAM' if y in ('P', 'A')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['sP2', 'sP3', 'sA2', 'sA3', 'mP2', 'mP3', 'mA2', 'mA3']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x + y + z for x in 'spam' if x in 'sm'\n",
    "           for y in 'SPAM' if y in ('P', 'A')\n",
    "           for z in '123' if z > '1']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1 列表解析和矩阵  \n",
    "使用 Python 编写矩阵的一个基本方法就是使用嵌套的列表结构："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 5, 6]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M = [[1, 2, 3],\n",
    "    [4, 5, 6],\n",
    "    [7, 8, 9]]\n",
    "\n",
    "N = [[2, 2, 2],\n",
    "    [3, 3, 3],\n",
    "    [4, 4, 4]]\n",
    "\n",
    "M[1]                                # 第二行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M[1][2]                             # 第二行，第三列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 5, 8]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[row[1] for row in M]               # 第二列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 5, 8]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[M[row][1] for row in (0, 1, 2)]    # 使用偏移"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 5, 9]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[M[i][i] for i in range(len(M))]    # 对角线元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3, 5, 7]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[M[i][len(M)-1-i] for i in range(len(M))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[11, 12, 13, 14, 15, 16, 17, 18, 19]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[col + 10 for row in M for col in row]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[11, 12, 13], [14, 15, 16], [17, 18, 19]]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[[col + 10 for col in row] for row in M]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "列表解析可以混合多个矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 12, 15, 18, 28, 32, 36]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[M[row][col] * N[row][col] for row in range(3) for col in range(3)]  # 矩阵对元素的乘积，单层列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[2, 4, 6], [12, 15, 18], [28, 32, 36]]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[[M[row][col] * N[row][col] for col in range(3)] for row in range(3)]   # 嵌套列表结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[2, 4, 6], [12, 15, 18], [28, 32, 36]]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[[col1 * col2 for (col1, col2) in zip(row1, row2)] for (row1, row2) in zip(M, N)]  # 使用 zip 组合要相乘的项"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 2. 生成器函数和表达式  \n",
    "Python 提供了工具在需要的时候才产生结果，而不是立即产生结果。有两种语言结构尽可能地延迟结果创建。  \n",
    "- 生成器函数：编写为常规的 def 语句，但是使用 yield 语句一次返回一个结果，在每个结果之间挂起和继续它们的状态。\n",
    "- 生成器表达式：类似于列表解析，但是它们返回按需产生结果的一个对象，而不是构建一个结果列表。\n",
    "\n",
    "由于二者都不会一次性构建一个列表，它们节省了内存空间，而且允许计算时间分散到各个结果请求。  \n",
    "\n",
    "## 2.1 生成器函数：yield VS return  \n",
    "生成器函数，编写可以送回一个值并随后从其退出的地方继续的函数，因为它们随着时间产生值的一个序列。  \n",
    "\n",
    "一般来说，生成器函数和常规函数一样，然而，当创建时，生成器函数自动实现迭代协议，以便可以出现在迭代背景中。  \n",
    "\n",
    "**状态挂起**  \n",
    "生成器函数自动在生成值的时候挂起并继续函数的执行。由于生成器函数在挂起时保存的状态包含它们的整个本地作用域，当函数恢复时，它们的本地变量保持了信息并且使其可用。  \n",
    "\n",
    "yield 语句挂起该函数并向调用者发送回一个值，但是，保留足够的状态以使得函数能够从它离开的地方继续。当继续时，函数在上一个 yield 返回后立即继续执行。这允许代码随着时间产生一系列的值，而不是一次计算它们。  \n",
    "\n",
    "**迭代协议整合**  \n",
    "可迭代对象定义了一个 `__next__` 方法，它返回迭代中的下一项，或者引发一个特殊的 StopIteration 异常来终止迭代。一个对象的迭代器用 iter 内置函数接收。  \n",
    "\n",
    "如果支持该协议，Python 的 for 循环以及其他的迭代环境，使用这种迭代协议来遍历一个序列或值生成器；如果不支持，迭代返回去重复索引序列。  \n",
    "\n",
    "要支持这一协议，函数包含一条 yield 语句，该语句特别编译为生成器。当调用时，它们返回一个生成器对象，该对象支持一个名为 `__next__` 的自动创建的方法来开始或继续执行的接口。  \n",
    "\n",
    "生成器函数也可能有一条 return 语句，总是在 def 语句块的末尾，直接终止值的生成。从技术上讲，可以在任何常规函数退出执行后，引发一个 StopIteration 异常来实现。从调用者的角度来看，生成器的 `__next__` 方法继续函数并且运行到下一个 yield 结果返回或引发一个 StopIteration 异常。  \n",
    "\n",
    "**生成器函数应用**  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 生成一系列的数字的平方\n",
    "def gensquares(N):        \n",
    "    for i in range(N):\n",
    "        yield i ** 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数在每次循环时都会产生一个值，之后将其返还给它的调用者。当它被暂停后，它的上一个状态保存了下来，并且在 yield 语句之后控制器马上被回收。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 : 1 : 4 : 9 : 16 : "
     ]
    }
   ],
   "source": [
    "for i in gensquares(5):\n",
    "    print(i, end=' : ')          # 打印最后生成的值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为了终止生成值，函数可以使用一个无值的 return 语句，或者在函数主体最后简单地让控制器脱离。  \n",
    "\n",
    "看看在 for 里面发生了什么。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object gensquares at 0x00000155CCB699E8>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = gensquares(4)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-5e4e57af3a97>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "next(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意迭代协议中顶层的 iter 调用在这里不需要，因为生成器是自己的迭代器，仅支持一个活跃的迭代扫描。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = gensquares(5)\n",
    "iter(y) is y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**为什么使用生成器函数？**  \n",
    "我们能够简单地一次就构建一个所获得的值的列表。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 : 1 : 4 : 9 : 16 : "
     ]
    }
   ],
   "source": [
    "def buildsquares(n):\n",
    "    res = []\n",
    "    for i in range(n): res.append(i ** 2)\n",
    "    return res\n",
    "\n",
    "for x in buildsquares(5):\n",
    "    print(x, end=' : ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "还能使用 for 循环、map 或者列表解析来实现："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 : 1 : 4 : 9 : 16 : "
     ]
    }
   ],
   "source": [
    "for x in [n ** 2 for n in range(5)]:\n",
    "    print(x, end=' : ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 : 1 : 4 : 9 : 16 : "
     ]
    }
   ],
   "source": [
    "for x in map((lambda n: n ** 2), range(5)):\n",
    "    print(x, end=' : ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "尽管如此，生成器在内存使用和性能方面都更好。它们允许函数避免临时再做所有的工作，当结果的列表很大或者在处理每一个结果都需要很多时间时，这一点尤其有用。生成器将在循环迭代中处理一系列值的时间分布开来。  \n",
    "\n",
    "对于更多高级的应用，它们提供了一个更简单的替代方案来手动保存类的对象的迭代中的状态。有了生成器，函数变量就能进行自动的保存和恢复。  \n",
    "\n",
    "生成器函数能够在任意类型的对象上进行操作和返回，包括元组调用，enumeration 和字典解析："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('AAA', 'BBB', 'CCC')"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def ups(line):\n",
    "    for sub in line.split(','):         # 子字符串生成器\n",
    "        yield sub.upper()\n",
    "\n",
    "tuple(ups('aaa,bbb,ccc'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0: 'AAA', 1: 'BBB', 2: 'CCC'}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{i: s for (i, s) in enumerate(ups('aaa,bbb,ccc'))}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 2.2 生成器表达式：迭代器遇到列表解析  \n",
    "生成器表达式就像一般的列表解析一样，但是它们是括在圆括号中而不是方括号中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x000001ACF4CD9BF8>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(x ** 2 for x in range(4))         "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生成器表达式不是在内存中构建结果，而是返回一个生成器对象，这个对象将会支持迭代协议。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "G = (x ** 2 for x in range(4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-380e167d6934>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mG\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "next(G)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "作为可迭代的，生成器表达式可以出现在任意迭代环境中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAABBBCCC'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 字符串 join 方法中使用生成器表达式\n",
    "''.join(x.upper() for x in 'aaa,bbb,ccc'.split(','))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('aaa\\n', 'ccc\\n')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 元组赋值中使用生成器表达式\n",
    "a, b, c = (x + '\\n' for x in 'aaa,bbb,ccc'.split(','))\n",
    "a, c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果生成器表达式是在其他的括号之内，就像在那些函数调用之中，在这种情况下，生成器自身的括号就不是必须的了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(x ** 2 for x in range(4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 4, 9]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sorted(x ** 2 for x in range(4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 4, 1, 0]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sorted((x ** 2 for x in range(4)), reverse=True)    # 还是需要额外的括号"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**为什么使用生成器表达式？**  \n",
    "生成器表达式是对内存空间的一个优化，它们不需要像列表解析一样一次构造出整个列表结果。  \n",
    "\n",
    "生成器表达式可能比列表解析运行得稍慢，因此，它们最好仅在非常大的结果集合或者不能等待所有结果生成的应用中使用。  \n",
    "\n",
    "**生成器表达式 VS map**  \n",
    "生成器表达式经常和 map 调用是等效的，因为两者都是按需求生成结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(abs, (-1, -2, 3, 4)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(abs(x) for x in (-1, -2, 3, 4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x: x * 2, (1, 2, 3, 4)))    # 非函数调用时，生成器表达式可能更简单"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(x * 2 for x in (1, 2, 3, 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在文字处理中，列表解析生成一个额外的临时结果列表，这完全没有意义。当操作不是一个调用时，map 相比于生成器表达式语法，丢失了简便性这一要点："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAABBBCCC'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "line = 'aaa,bbb,ccc'\n",
    "''.join([x.upper() for x in line.split(',')])    # 生成无意义的列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAABBBCCC'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(x.upper() for x in line.split(','))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAABBBCCC'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(map(str.upper, line.split(',')))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'aaaaaabbbbbbcccccc'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(x * 2 for x in line.split(','))           # 生成器表达式更简单"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'aaaaaabbbbbbcccccc'"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(map(lambda x: x * 2, line.split(',')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "map 和生成器表达式都可以任意嵌套，需要一个 list 调用或者其他迭代环境来开始生成结果的进程。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * 2 for x in [abs(x) for x in (-1, -2, 3, 4)]]  # 列表解析需要生成两个列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x:x * 2, map(abs, (-1, -2, 3, 4))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(x * 2 for x in (abs(x) for x in (-1, -2, 3, 4)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "非嵌套方法可以提供更简洁的解决方法，且仍然利用了生成器的优点："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(abs(x) * 2 for x in (-1, -2, 3, 4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**生成器表达式 VS filter**  \n",
    "生成器表达式支持所有常规的列表解析语法——包括 if 分句。使用 if 分句的生成器表达式在操作上和 filter 等效："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'aabbb'"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "line = 'aa bbb c'\n",
    "''.join(x for x in line.split() if len(x) > 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'aabbb'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(filter(lambda x: len(x) > 1, line.split()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "至于列表解析，在 filter 结果上添加处理过程也需要 map，这使得 filter 比生成器表达式更加复杂："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AABBB'"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(x.upper() for x in line.split() if len(x) > 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AABBB'"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''.join(map(str.upper, filter(lambda x: len(x) > 1, line.split())))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 生成器是单迭代器对象  \n",
    "生成器函数和生成器表达式自身都是迭代器，并由此只支持一次活跃迭代。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G = (c * 4 for c in 'SPAM')\n",
    "iter(G) is G"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果手动使用多迭代器来迭代结果流，它们将会指向相同的位置。一旦任何迭代器运行到完成，所有的迭代器都将用尽，必须产生一个新的生成器以再次开始。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'SSSS'"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "I1 = iter(G)\n",
    "next(I1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'PPPP'"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(I1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "I2 = iter(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAAA'"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(I2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'MMMM'"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(I2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "I3 = iter(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-40-6626ccf10866>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mI3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "next(I3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**yield from Extension**  \n",
    "Python 3.3 介绍了 yield 语句的扩展语法，允许使用 from generator 分句代表子生成器。简单情况下，它相当于一个 yield 的 for 循环。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 0, 1, 4, 9, 16]"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def both(N):\n",
    "    for i in range(N): yield i\n",
    "    for i in (x ** 2 for x in range(N)): yield i\n",
    "    \n",
    "list(both(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 0, 1, 4, 9, 16]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def both(N):                   # 新的语法更简单明确\n",
    "    yield from range(N)\n",
    "    yield from (x ** 2 for x in range(N))\n",
    "    \n",
    "list(both(5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4 示例\n",
    "示例只在序列中有效。  \n",
    "\n",
    "**打乱序列**  \n",
    "传统分片和拼接可以将序列重新排列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pams amsp mspa spam "
     ]
    }
   ],
   "source": [
    "L, S = [1, 2, 3], 'spam'\n",
    "for i in range(len(S)):\n",
    "    S = S[1:] + S[:1]           # 将前面的元素移至末尾\n",
    "    print(S, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "spam pams amsp mspa "
     ]
    }
   ],
   "source": [
    "for i in range(len(S)):\n",
    "    X = S[i:] + S[:i]           # 后面部分 + 前面部分\n",
    "    print(X, end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**生成器函数**  \n",
    "生成器函数在活动时保留了本地作用域状态，最小化内存空间需要，将工作分为更短的时间片。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['pams', 'amsp', 'mspa', 'spam']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def scramble(seq):\n",
    "    for i in range(len(seq)):\n",
    "        seq = seq[1:] + seq[:1]\n",
    "        yield seq\n",
    "\n",
    "list(scramble('spam'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(2, 3, 1), (3, 1, 2), (1, 2, 3)]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(scramble((1, 2, 3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**生成器表达式**  \n",
    "表达式不如完整函数灵活，但是它们能自动生成值，因此通常更简洁。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['spam', 'pams', 'amsp', 'mspa']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S = 'spam'\n",
    "G = (S[i:] + S[:i] for i in range(len(S)))\n",
    "list(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['spam', 'pams', 'amsp', 'mspa']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "F = lambda seq: (seq[i:] + seq[:i] for i in range(len(seq)))\n",
    "list(F(S))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.5 示例：用迭代工具模拟 map  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('a', 'x'), ('b', 'y'), ('c', 'z')]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "S1 = 'abc'\n",
    "S2 = 'xyz123'\n",
    "list(zip(S1, S2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(-2,), (-1,), (0,), (1,), (2,)]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(zip([-2, -1, 0, 1, 2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 2), (2, 3), (3, 4)]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(zip([1, 2, 3], [2, 3, 4, 5]))   # zip 组合元素，在最短处截断"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 1, 0, 1, 2]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(abs, [-2, -1, 0, 1, 2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 8, 81]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用多个序列参数，map 以与 zip 配对元素相同的方式，把函数映射到取自每个序列的元素\n",
    "list(map(pow, [1, 2, 3], [2, 3, 4, 5]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**编写自己的 map(func, ...)**  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 1, 0, 1, 2]\n",
      "[1, 8, 81]\n"
     ]
    }
   ],
   "source": [
    "def mymap(func, *seqs):\n",
    "    res = []\n",
    "    for args in zip(*seqs):\n",
    "        res.append(func(*args))\n",
    "    return res\n",
    "\n",
    "print(mymap(abs, [-2, -1, 0, 1, 2]))\n",
    "print(mymap(pow, [1, 2, 3], [2, 3, 4, 5]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 使用列表解析\n",
    "def mymap(func, *seqs):\n",
    "    return [func(*args) for args in zip(*seqs)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 使用生成器\n",
    "def mymap(func, *seqs):\n",
    "    res = []\n",
    "    for args in zip(*seqs):\n",
    "        yield func(*args)\n",
    "    \n",
    "def mymap(func, *seqs):\n",
    "    return (func(*args) for args in zip(*seqs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 解析语法总结  \n",
    "在 Python 3.X 中还有两种可用的解析表达式形式：集合解析和字典解析。\n",
    "- 对于集合，新的常量形式{1, 3, 2}等同于 set([1, 3, 2])，并且新的集合解析语法 `{f(x) for x in S if P(x)}` 就像是生成器表达式 `set(f(x) for x in S if P(x))`，其中 f(x) 是一个任意的表达式。\n",
    "- 对于字典，新的字典解析语法 `{key: val for (key, val) in zip(keys, vals)}` 像 `dict(zip(keys, vals))` 形式一样工作，并且 `{x: f(x) for x in items}` 像生成器表达式 `dict((x, f(x)) for x in items)` 一样工作。\n",
    "\n",
    "**Python 3.X 中所有解析替代方式的总结**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 列表解析：创建列表\n",
    "[x * x for x in range(10)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x0000019DAA566E08>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 生成器表达式：生成元素\n",
    "(x * x for x in range(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 集合解析\n",
    "{x * x for x in range(10)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 字典解析\n",
    "{x: x * x for x in range(10)}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.1 作用域和解析变量  \n",
    "Python 3.X 中本地化四种形式的循环变量——生成器、集合、字典和列表解析中的临时循环变量名对于表达式是本地的。它们不和外部的名称冲突，也在外部不可用。和 for 循环迭代语句工作方式不同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x0000019DAA566F68>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(M for M in range(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'M' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-23-370751da74d8>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mM\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'M' is not defined"
     ]
    }
   ],
   "source": [
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = 99\n",
    "[X for X in range(5)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "99"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "Y = 99\n",
    "for Y in range(5): pass         # 循环语句不本地化变量名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 3.2 针对集合和字典的扩展的解析语法  \n",
    "集合和字典解析都支持嵌套相关的 if 子句从结果中过滤掉元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 4, 16, 36, 64]"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * x for x in range(10) if x % 2 == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0, 4, 16, 36, 64}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x * x for x in range(10) if x % 2 == 0}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0: 0, 2: 4, 4: 16, 6: 36, 8: 64}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x: x * x for x in range(10) if x % 2 == 0}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "嵌套的 for 循环也有效。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 6, 7, 6, 7, 8, 7, 8, 9]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x + y for x in [1, 2, 3] for y in [4, 5, 6]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{5, 6, 7, 8, 9}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x + y for x in [1, 2, 3] for y in [4, 5, 6]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 6, 2: 6, 3: 6}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x: y for x in [1, 2, 3] for y in [4, 5, 6]}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "集合解析和字典解析也可以在任何类型的可迭代对象上迭代——列表、字符串、文件、范围以及支持迭代协议的任何其他类型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ac', 'ad', 'bc', 'bd'}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x + y for x in 'ab' for y in 'cd'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ac': (97, 99), 'ad': (97, 100), 'bc': (98, 99), 'bd': (98, 100)}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{x + y: (ord(x), ord(y)) for x in 'ab' for y in 'cd'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'sausagesausage', 'spamspam'}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{k * 2 for k in ['spam', 'ham', 'sausage'] if k[0] == 's'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'SPAM': 'spamspam', 'SAUSAGE': 'sausagesausage'}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{k.upper(): k * 2 for k in ['spam', 'ham', 'sausage'] if k[0] == 's'}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
